/* eslint-disable no-void */
// eslint-disable-next-line max-classes-per-file
import Sub from 'function/sub';

interface LoadScriptOptions {
  type: string
  charset: string
  async: boolean
}

/**
 * TODO
 * parallel 并行加载js 单个或者多个
 * series 同步加载js -> a.js -> b.js
 * 参数只能以数组形式
 */
export class LoadScript extends Sub {
  /**
   * 已被加载 script
   */
  private static load: Record<string, HTMLScriptElement> = Object.create(null)

  private el: HTMLScriptElement | undefined

  private options: LoadScriptOptions = {
    type: 'text/javascript', charset: 'utf8', async: true,
  }

  constructor(options?: LoadScriptOptions) {
    super();

    if (options) this.options = Object.assign(this.options, options);
  }

  private createElement(url: string, options: LoadScriptOptions) {
    console.warn(options);
    const el = document.createElement('script');
    const haveLoadScript = Object.prototype.hasOwnProperty.call(LoadScript.load, url);

    if (haveLoadScript) {
      if (LoadScript.load[url].getAttribute('load') !== 'load') {
        console.warn(`已有script ${url} 正在加载`);
        this.addEventListener(LoadScript.load[url]);
        return void (0);
      }

      if (Promise) {
        Promise.resolve().then(() => this.emit('load'));
      } else {
        setTimeout(() => this.emit('load'), 0);
      }

      console.warn(`已有script ${url} 加载完毕`);
      return void (0);
    }

    LoadScript.load[url] = el;

    el.src = url;
    el.async = options.async;
    el.charset = options.charset;
    el.type = options.type;
    return el;
  }

  private addEventListener(el: HTMLScriptElement) {
    el.addEventListener('load', () => {
      this.emit('load', this);
      if (!el.getAttribute('load')) el.setAttribute('load', 'load');
    });

    document.getElementsByTagName('head')[0].appendChild(el);
  }

  public load(url: string, options?: LoadScriptOptions) {
    this.el = this.createElement(url, options || this.options);

    this.el && this.addEventListener(this.el);
    return this;
  }
}
